﻿// This sample code has been built using EMC Documentum Foundation Services (DFS)
// version 6.5 SP1, Visual Studio 2008 and .NET 3.5 (Windows Communication Foundation
// "v2" and LINQ to XML--System.Xml.Linq). It is not supported by EMC.
//
// In order to build and run this sample you must have DFS 6.5 SP1 (i.e. its web 
// services) properly deployed (e.g. into a JEE application server such as JBoss 
// 4.2.2).
//
// The primary intent of this sample code is to demonstrate direct-to-WSDL consumption
// of DFS using standard Microsoft tools (Visual Studio) and frameworks (WCF).
//
// Please visit the EMC Developer Network for more on DFS:
//     https://community.emc.com/community/edn/documentum
using System.Collections.Generic;
using System.Globalization;
using System.ServiceModel.Channels;
using System.Xml;
using System.Xml.Serialization;

using System.IO;
using System.Xml.Linq;
using System.Linq;
using System.Text;
using System.ServiceModel;

using D6.DFS.DevUtility.D6ContextRegistry;
using D6.DFS.DevUtility.D6ObjectService;
using D6.DFS.DevUtility.D6QueryService;
using D6.DFS.DevUtility.D6SchemaService;
using D6.DFS.DevUtility.D6SearchService;
using System;


namespace D6.DFS.Consumer
{

    #region ServiceContextHeader

    public class ServiceContextHeader : MessageHeader
    {
        private readonly List<RepositoryIdentity> repositoryIdentities = new List<RepositoryIdentity>();
        private D6.DFS.DevUtility.D6ContextRegistry.ContentTransferProfile contentTransferProfile;

        public void AddRepositoryIdentity(RepositoryIdentity rid)
        {
            if (rid == null)
                return;

            repositoryIdentities.Add(rid);
        }

        public void AddContentTransferProfile(D6.DFS.DevUtility.D6ContextRegistry.ContentTransferProfile ctp)
        {
            if (ctp == null)
                return;

            contentTransferProfile = ctp;
        }

        protected override void OnWriteHeaderContents(XmlDictionaryWriter writer, MessageVersion messageVersion)
        {
            // If there are no ids, do nothing
            if (repositoryIdentities.Count < 1)
                return;

            // Add ids to the ServiceContext
            ServiceContext serviceContext = new ServiceContext();
            serviceContext.Identities = new Identity[repositoryIdentities.Count];
            for (int x = 0; x < repositoryIdentities.Count; x++)
                serviceContext.Identities[x] = repositoryIdentities[x];

            // If there is a ContentTransferProfile, add it
            if (contentTransferProfile != null)
            {
                serviceContext.Profiles = new D6.DFS.DevUtility.D6ContextRegistry.ContentTransferProfile[1];
                serviceContext.Profiles[0] = contentTransferProfile;
            }

            // Serialize the objects to XML
            XDocument doc = null;
            using (StringWriter sw = new StringWriter(CultureInfo.CurrentCulture))
            {
                XmlSerializer xs = new XmlSerializer(typeof(ServiceContext));
                xs.Serialize(sw, serviceContext);
                doc = XDocument.Load(new StringReader(sw.ToString()));
            }

            // Add Identities to the ServiceContext header
            foreach (XElement el in doc.Descendants(XName.Get("Identities", "http://context.core.datamodel.fs.documentum.emc.com/")))
            {
                XmlReader r = XmlReader.Create(new StringReader(el.ToString()));
                writer.WriteNode(r, true);
            }

            // Add Profiles to the ServiceContext header 
            if (serviceContext.Profiles != null)
            {
                foreach (XElement el in doc.Descendants(XName.Get("Profiles", "http://context.core.datamodel.fs.documentum.emc.com/")))
                {
                    XmlReader r = XmlReader.Create(new StringReader(el.ToString()));
                    writer.WriteNode(r, false);
                }
            }
        }

        public override string Name
        {
            get { return "ServiceContext"; }
        }

        public override string Namespace
        {
            get { return "http://context.core.datamodel.fs.documentum.emc.com/"; }
        }
    }

    #endregion ServiceContextHeader


    #region DfsConsumptionPattern

    public abstract class DfsConsumer
    {


        #region Attributes

        protected Repository[] m_repositoryList = null;
        protected ServiceContextHeader m_scx = null;
        protected SearchServicePortClient m_searchService = null;
        protected SchemaServicePortClient m_schemaService = null;
        protected ObjectServicePortClient m_objectService = null;
        protected QueryServicePortClient m_queryService = null;

        protected Repository m_currRepository = null;
        protected string m_currRepositoryName = null;
        protected string m_currRepositoryUserLogin = null;
        protected string m_currRepositoryUserPassword = null;

        protected int m_total_results_to_return = 4;

        protected string m_exceptionInfo = null;

        #endregion Attributes

        #region Properties
        public string[] Repositories
        {
            get
            {
                List<string> repositoryNames = new List<string>();

                foreach (Repository repositoryItem in GetRepositoryList())
                {
                    repositoryNames.Add(repositoryItem.name);
                }

                return repositoryNames.ToArray();
            }
        }

        public string ErrorMessage
        {
            get
            {
                return m_exceptionInfo;
            }
        }

        public int Results_To_Return
        {
            get
            {
                return m_total_results_to_return;
            }
            set
            {
                m_total_results_to_return = value;
            }
        }


        #endregion Properties


        #region Methods

        public DfsConsumer()
        {
            m_searchService = new SearchServicePortClient("SearchServicePort");
            m_schemaService = new SchemaServicePortClient("SchemaServicePort");
            m_objectService = new ObjectServicePortClient("ObjectServicePort");
            m_queryService = new QueryServicePortClient("QueryServicePort");

            m_scx = new ServiceContextHeader();
            RepositoryIdentity repositoryId = new RepositoryIdentity();
            repositoryId.repositoryName = "DMS";
            repositoryId.userName = "";
            repositoryId.password = "";

            m_scx.AddRepositoryIdentity(repositoryId);
        }

        public DfsConsumer(string repository, string username, string password)
        {
            m_searchService = new SearchServicePortClient("SearchServicePort");
            m_schemaService = new SchemaServicePortClient("SchemaServicePort");
            m_objectService = new ObjectServicePortClient("ObjectServicePort");
            m_queryService = new QueryServicePortClient("QueryServicePort");

            m_scx = new ServiceContextHeader();
            RepositoryIdentity repositoryId = new RepositoryIdentity();
            repositoryId.repositoryName = repository;
            repositoryId.userName = username;
            repositoryId.password = password;

            m_currRepositoryName = repositoryId.repositoryName;

            m_scx.AddRepositoryIdentity(repositoryId);
        }


        protected Repository[] GetRepositoryList()
        {
            if (null == m_repositoryList || m_repositoryList.Count() == 0)
            {
                try
                {

                    using (OperationContextScope scope = new OperationContextScope(new OperationContext(m_searchService.InnerChannel)))
                    {
                        OperationContext.Current.OutgoingMessageHeaders.Add(m_scx);
                        m_repositoryList = m_searchService.getRepositoryList(null);
                    }


                }
                catch (Exception ex)
                {
                    m_exceptionInfo = ex.ToString();
                }

            }

            return m_repositoryList;
        }

        protected void getDctmObject(String customType)
        {
            D6.DFS.DevUtility.D6ObjectService.DataPackage dataPackage = null;

            try
            {
                //find the custom type to return
                D6.DFS.DevUtility.D6ObjectService.Qualification q = new D6.DFS.DevUtility.D6ObjectService.Qualification();
                q.String = "dm_type WHERE name = '" + customType + "'";
                q.qualificationValueType = D6.DFS.DevUtility.D6ObjectService.QualificationValueType.STRING;
                q.qualificationValueTypeSpecified = true;

                //Set the identity
                D6.DFS.DevUtility.D6ObjectService.ObjectIdentity objId = new D6.DFS.DevUtility.D6ObjectService.ObjectIdentity();
                objId.valueType = D6.DFS.DevUtility.D6ObjectService.ObjectIdentityType.QUALIFICATION;
                objId.valueTypeSpecified = true;
                objId.Item = q;
                objId.repositoryName = m_currRepositoryName;

                D6.DFS.DevUtility.D6ObjectService.ObjectIdentitySet objectIdSet = new D6.DFS.DevUtility.D6ObjectService.ObjectIdentitySet();
                objectIdSet.Identities = new D6.DFS.DevUtility.D6ObjectService.ObjectIdentity[1];
                objectIdSet.Identities[0] = objId;

                D6.DFS.DevUtility.D6ObjectService.PropertyProfile propertyProfile = new D6.DFS.DevUtility.D6ObjectService.PropertyProfile();
                String[] attributes = new String[1];
                attributes[0] = "test_value_assistance";
                propertyProfile.IncludeProperties = attributes;

                D6.DFS.DevUtility.D6ObjectService.OperationOptions opsOptions = new D6.DFS.DevUtility.D6ObjectService.OperationOptions();
                opsOptions.Profiles = new D6.DFS.DevUtility.D6ObjectService.Profile[1];
                opsOptions.Profiles[0] = propertyProfile;

                using (OperationContextScope scope = new OperationContextScope(m_objectService.InnerChannel))
                {
                    OperationContext.Current.OutgoingMessageHeaders.Add(m_scx);
                    //m_schemaService.getDynamicAssistValues("DMS", "DEFAULT", "dlau_custom_type", "value_assistance", property_set, null);

                    dataPackage = m_objectService.get(objectIdSet, opsOptions);


                }

            }
            catch (Exception ex)
            {
                m_exceptionInfo = ex.ToString();
            }
        }


        public void SetCurrentRepository(String currRepositoryName, String username, String password)
        {
            if (String.IsNullOrEmpty(currRepositoryName))
            {
                return;
            }
            if (null == m_repositoryList || m_repositoryList.Count() == 0)
            {
                return;
            }
            if (String.IsNullOrEmpty(username))
            {
                return;
            }
            if (String.IsNullOrEmpty(password))
            {
                return;
            }

            m_currRepositoryName = currRepositoryName;
            m_currRepositoryUserLogin = username;
            m_currRepositoryUserPassword = password;

            IEnumerable<Repository> rCurrRepository = null;

            try
            {
                rCurrRepository = from Repository r in m_repositoryList
                                  where r.name.Equals(currRepositoryName)
                                  select r;
            }
            catch (Exception ex)
            {
                m_exceptionInfo = ex.ToString();
            }

            try
            {
                if (null == rCurrRepository || rCurrRepository.Count() == 0)
                {
                    return;
                }

                m_currRepository = rCurrRepository.First<Repository>();
            }
            catch (Exception ex)
            {
                m_exceptionInfo = ex.ToString();
            }

            m_scx = new ServiceContextHeader();
            RepositoryIdentity repositoryId = new RepositoryIdentity();
            repositoryId.repositoryName = m_currRepository.name;
            repositoryId.userName = m_currRepositoryUserLogin;
            repositoryId.password = m_currRepositoryUserPassword;

            m_scx.AddRepositoryIdentity(repositoryId);


        }


        public void ExecuteDQL(String dqlStr)
        {

            if (String.IsNullOrEmpty(dqlStr))
            {
                return;
            }

            try
            {

                using (OperationContextScope scope = new OperationContextScope(m_queryService.InnerChannel))
                {
                    OperationContext.Current.OutgoingMessageHeaders.Add(m_scx);
                    D6.DFS.DevUtility.D6QueryService.PassthroughQuery query = new D6.DFS.DevUtility.D6QueryService.PassthroughQuery();
                    query.queryString = dqlStr;
                    query.repositories = new String[1];
                    query.repositories[0] = m_currRepositoryName;

                    D6.DFS.DevUtility.D6QueryService.QueryExecution queryExec = new D6.DFS.DevUtility.D6QueryService.QueryExecution();
                    queryExec.cacheStrategyType = D6.DFS.DevUtility.D6QueryService.CacheStrategyType.BASIC_FILE_CACHE_STRATEGY;
                    queryExec.cacheStrategyTypeSpecified = true;
                    queryExec.maxResultPerSource = -1;
                    queryExec.maxResultCount = 2000;
                    queryExec.startingIndex = 0;                    

                    D6.DFS.DevUtility.D6QueryService.QueryResult results = null;

                    results = m_queryService.execute(query, queryExec, null);

                    if (null != results)
                    {
                        processQueryResults(results);
                    }

                }



            }
            catch (Exception ex)
            {
                m_exceptionInfo = ex.ToString();
            }


        }

        protected abstract void processQueryResults(D6.DFS.DevUtility.D6QueryService.QueryResult repositoryItems);


        #endregion Methods

    }

#endregion DfsConsumptionPattern

    

}
